/*
 * Copyright 2009 XueSong Guo.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.webwheel.database;

import cn.webwheel.database.engine.IPoolFactory;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * the core interface of DBWheel, and the only interface used by the DBWheel user.<br/>
 */
public interface IPool {

    /**
     * sql enhanced object factory and pool method.<br/>
     * the cls parameter should be an abstract class or an interface, and all abstract methods of that must be annotated by DBWheel annotations - Select or Update.<br/>
     * if the cls parameter is a normal class, then an instance of it created by object factory object set by user when IPool is created will be returned.<br/>
     * <code><pre><b>example:</b>
     * public interface Queries {
     *   {@code @}Select("select count(*) from student")
     *   int countStudents();
     * }
     * public class Main {
     *   public static void main(String[] args) {
     *     IPool pool = DBWheel.createIPool(...);
     *     Queries queries = pool.get(Queries.class);
     *     System.out.println("there are " + queries.countStudents() + " students.");
     *   }
     * }
     * </pre></code>
     * @param cls an abstract class with methods annotated by DBWheel annotations: Select, Update
     * @return sql enhanced object
     * @throws IException exception while creating sql enchanced object
     */
    <T> T get(Class<T> cls) throws IException;

    /**
     * start a database transaction.<br/>
     * when there's already a transaction, it do nothing.
     * @throws SQLException sql exception
     */
    void startTransaction() throws SQLException;

    /**
     * commit current transaction and close database connection.<br/>
     * when the transaction is nested in outer transaction, it do nothing.
     * @throws SQLException sql exception
     * @throws IllegalStateException there's no transaction open.
     */
    void commitTransaction() throws SQLException;

    /**
     * rollback current transaction and close database connection.<br/>
     * when the transaction is nested in outer transaction, it do nothing.
     * @throws SQLException sql exception
     * @throws IllegalStateException there's no transaction open.
     */
    void rollbackTransaction() throws SQLException;

    /**
     * get a new database connection, must be closed by using {@link cn.webwheel.database.IPool#closeConnection(java.sql.Connection)}.
     * @return a new database connection
     * @throws SQLException sql exception
     */
    Connection getConnection() throws SQLException;

    /**
     * close a database connection got by using {@link IPool#getConnection()}.
     * @param con database connection
     * @throws SQLException sql exception
     */
    void closeConnection(Connection con) throws SQLException;

    /**
     * retieve factory
     * @return factory which create this ipool
     */
    IPoolFactory getFactory();
}
